import {observable, action} from 'mobx';
import {WeaForm} from 'comsMobx';
import {WeaTableNew} from 'comsMobx';
import cloneDeep from 'lodash/cloneDeep';
import isEmpty from 'lodash/isEmpty';
import * as mobx from 'mobx';
import * as WORKFLOWDESIGN_API from '../apis/freeFlowTemplate';
import {WeaLocaleProvider} from 'ecCom';
import {message, Modal} from 'antd'

const {TableStore} = WeaTableNew;
const getLabel = WeaLocaleProvider.getLabel;
const {toJS} = mobx;

import {calculateNodePoint} from '../components/wf-free-chart/freeNodeChartUtil';

export class WorkflowNewDesignStore {

    @observable loading = false;
    @observable workflowDesignShow = false;
    @observable shouldPostXml = true;
    workflowDesignId = '';
    // 自由流程
    @observable freeIsEditNode = false;
    @observable freeIsEditGroup = false;
    @observable currentFreeWfEditState = false;
    /**
    wfFreeDatas : {
        startId : [],
        startId : [],
    }
     */
    @observable wfFreeDatas = null; 
    /**
    wfFreeDatasPoints : {
        startId_index : {},//index 为在当前 起始点数据数组中的 数组下标
        startId_index : {},
    }
     */
    @observable wfFreeDatasPoints = {};
    @observable beforeSavedDatas = {};

    @observable svgPathLine = {};

    //操作者是否必填
    operatorMustInput = false;
    //签批设置项
    groupApprovalSettings = {};
    // 详细设置
    @observable freeDetailSetConditions = [];
    @observable detailForm_1 = new WeaForm();
    // 
    @observable currentChoosedItemDataIndex = '';
    @observable currentChoosedItemId = '';
    @observable currentMouseEneterItemId = '';
    @observable currentChoosedBranchId = '';
    @observable curRightDetailItemId = '';
    @observable curFloatSignNodeId = '';//加签时 悬浮时的节点
    @observable deleteIds = [];
    @observable currentPostParams = {
        currentPostRequestId: '',
        currentPostWorkflowId: '',
    };
    @observable nodeOperatorsReplaceDatas = {};
    @observable branchBorderColorShowId = '';
    @observable rightDetailShowSearchGroup = {//记录右侧操作面板的显隐
        "0":true,
        "1":false,
        "2":false,
    };
    @observable globalNextNodeEditPurview = 2;
    currentFlowingGroup = null;

    // 是否需要换行展示
    isNeedChangeRow = false;
    @observable currentAddDataId = 1;
    @observable rightDetailType = 'node'; // value : node || branch || signSet...
    // 拖拽记录参数
    @observable dragStartItemId = '';
    @observable dragEndItemId = '';
    // 保存验证结果对象
    @observable saveCheckResult = {};
    // 退回设置
    @observable returnBackDialogShow = false;
    @observable returnBackConditions = [];
    @observable returnBackForm = new WeaForm();
    @observable tempReturnBackValue = {};
    @observable componentNeedRender = 0;

    currentGlobalParam = {};

    // 记录所有操作者type-便于转换
    operatorTransType = {
        "com":0,
        "resource": 1,
        "subcom": 2,
        "dept": 3,
        "group": 4,
        "virtual_subcom": 5,
        "virtual_dept": 7,
        "all": 9
    };
    circulationParams = {//流转参数
        noPassedLinkColor: '#979797',//未走过的出口
        passedLinkColor: '#DC4446',//走过的出口
        forecastLinkColor: '#1BD1C5',//智能预测的出口
        passedNodeAndNoOPeration: {//走过的节点，点击无操作菜单
            backgroundColor: '#A9E2FF',
            borderColor: '#49A8D4',
            nodeColor: '#1E4F6D',
            operatorColor: '#3C74AF',
        },
        noPassedNodeShouldCheckRight: {//未走过的节点，根据当前节点权限判断是否有操作菜单
            backgroundColor: '#BFF3C3',
            borderColor: '#5ABD6B',
            nodeColor: '#466F4A',
            operatorColor: '#469454',
        },
        currentNodeAndNoOperation: {//当前到达节点，点击无操作菜单
            backgroundColor: '#FFE8CC',
            borderColor: '#F4B373',
            nodeColor: '#7C5323',
            operatorColor: '#C3822A',
        },
        currentMustPassNode: { //当前到达节点 且 必须通过
            backgroundColor: '#FFD1CC',
            borderColor: '#FF8376',
            nodeColor: '#B03528',
            operatorColor: '#E35B4D',
        },
        currentOperator: {//当前操作人
            backgroundColor: '#fee7cc',
            borderColor: '#ff3300',
            nodeColor: '',
            operatorColor: '',
        },
        forecastNode: { //预测出来的节点
            backgroundColor: '#98F6EF',
            borderColor: '#1BD1C5',
            nodeColor: '#087E76',
            operatorColor: '#087E76',
        }
    };
    // 加签参数
    @observable currentOrginSupPosition = {//根据起始，结束点计算出的辅助位置信息，连线 & 当前流转节点上的添加按钮
        startPosition: {},
        endPosition: {},
    }
    circulationOrginNode = {//原始流程图中的节点信息，如记录开始节点，结束节点和所有节点信息
        startOrginNodeId: '',
        endOrginNodeId: '',
        allOrginNodes: [],
    };
    @observable currentSignSetNode = {};//当前加签节点的参数数据
    @observable freeWfTrunkNodes = {};
    @observable allowAddNewBranch = false;
    signSetIsReadOnly = false;
    @observable validWorkFlowDatas = {//固定流程图数据
        cellMaxHeight : 0,//老流程图最大高度
        allValidNodes:[],//所有固定流程图节点
        currentStartNode : {},
        currentEndNodes : []
    };
    allValidNodesPostions = {};//所有固定节点的坐标位置
    allValidNodesNodeLinks = {};//所有固定节点 每个固定节点存在的出口信息
    nodeLinksConditions = {};
    betweenFreeNodeGap = 150; // 每个自由节点数据间的间隔
    currentValidStartNodeId = '';//当前流转到的固定节点id
    everyFreeNodeOffsetY = {};//记录下每个自由节点起始和结束线条Y轴偏移量
    /**从模板导入 */
    @observable modelImportModelShow = false;
    @observable importModelTableStore = new TableStore();
    modelAdCondition = [];
    @observable importModelForm = new WeaForm();
    @observable importModalAdShow = false;
    @observable allowTemplateImport = false;
    //存为模板
    saveAsTempCondition = [];
    @observable saveAsTempForm = new WeaForm();
    @observable saveAsTempModalShow = false;
    /***************** */
    @observable closeDialogIsConfirmed = false;

    /** 只读时点击节点 操作信息人员面板 */
    @observable popOperatorsPanelParams = {};
    
    /**移动端附加参数 */
    @observable mobileChoosedElement = {};
    mobileCurrentEditGroupId = '';
    @observable mobileChoosedElementIndex = '';
    @observable selectOperatorsMax = 100;

    //自动预测到的节点
    forecastNodeIds = "";

    constructor() {
        window.freeChartStore = this;
    }

    // 自由流程 ****************************************************************************
    @action
    initalFreeWfDatas = (params = {},callbackfun) => {
        this.currentPostParams = {...this.currentPostParams, ...params};
        this.loadNodeDetailInfo();
        WORKFLOWDESIGN_API.getFreeNodeInfo(params).then(result => {
            this.doActionToDatas_2(result, params);

            if(typeof callbackfun == 'function') {
                setTimeout(callbackfun, 500);
            }
        });

        WORKFLOWDESIGN_API.getSelectMaxRight({'actionType':'addFreeNode'}).then((data)=>{
            const {right = false,selectOperatorsMax = 100} = data;
            this.selectOperatorsMax = right ? undefined : selectOperatorsMax;
        });

    }
    @action
    doActionToDatas_2 = (result = {}, params = {},fromModelImport=false) => {
        const {isFree = '', templateid,isFromHtmlPage} = params;
        let {trunkNodes = {} , maxGroupNum=1 , allowImport = true,allowAddNewBranch=false,nextNodeEditPurview=2,
        nodeLinks={},freeNodeDatas={},currentStartNodeId,currentGroupId, forecastNodeIds} = result;

        this.currentGlobalParam = {currentStartNodeId,currentGroupId,allowAddNewBranch};

        //全局控制参数
        this.allowTemplateImport = allowImport;
        this.forecastNodeIds = forecastNodeIds;
        if(!fromModelImport){//导入后返回数据没有allowAddNewBranch
            this.allowAddNewBranch = allowAddNewBranch;
        }
        this.globalNextNodeEditPurview = nextNodeEditPurview;
        /**处理出口条件 */
        this.allValidNodesNodeLinks = nodeLinks;
        this.currentValidStartNodeId = currentStartNodeId;
        // *****
        this.currentAddDataId = maxGroupNum!=1?maxGroupNum:this.currentAddDataId;
        const {startGroup = {}, endGroup = {}} = trunkNodes;


        const currentBranchs = freeNodeDatas[currentStartNodeId] || [];
        let currentBranch = {};
        currentBranchs.map((item) => {
            if(item.id == currentGroupId) {
                currentBranch = item;
            }
        })
        const {freeEndNodeid='',freeStartNodeid=''} = currentBranch;
        /** 初始化加签信息*/
        if(isFree != '1' && templateid == '-1'){
            let {allValidNodes=[]} = this.validWorkFlowDatas;
            let currentStartNode = allValidNodes.filter(v=>v.nodeId ==currentStartNodeId)[0];
            const { value = '' , nodeType = ''} = currentStartNode;
            let obj = {
                nodeName : value,
                nodeType : nodeType
            };

            let flowType = '2';
            if(freeStartNodeid != '' && freeEndNodeid == freeStartNodeid) {
                flowType = '1';
            }
            obj['flowType'] = flowType;
            this.validWorkFlowDatas.currentStartNode = currentStartNode;
            this.currentSignSetNode={...this.currentSignSetNode,...obj};
        }
        this.freeWfTrunkNodes = trunkNodes;
        // 流转模板-拼接起始 结束节点
        if(templateid != '-1' && !isEmpty(trunkNodes)){
            let key_1 = Object.keys(freeNodeDatas)[0];
            let branchData  = {};
            if(typeof key_1 == 'undefined') {
                key_1 = trunkNodes['startGroup'].id;
            } else {
                branchData = freeNodeDatas[key_1][0];
            }
            freeNodeDatas[key_1] = [this.concatFreeFlowNodeDatas(branchData, trunkNodes)];
        }

        // 计算起始 结束线条等位置信息
        let obj = {
            startOrginNodeId: freeStartNodeid || this.circulationOrginNode.startOrginNodeId,
            endOrginNodeId:  freeEndNodeid || this.circulationOrginNode.endOrginNodeId
        }

        this.circulationOrginNode = {...this.circulationOrginNode, ...obj};
        // 初始化所有节点的节点操作者信息 并且获取当前正在流转的节点
        let resultsPlaceDatas = {} , curFlowingGroup = {} ;
        for(let key in freeNodeDatas){
            let arr = freeNodeDatas[key];
            arr.map(v=>{
                const _res = this.initAllNodesReplaceDatas(v);
                const _curRes = this.getcurrentFlowGroup(v);
                if(_curRes){
                    curFlowingGroup = _curRes;
                }
                resultsPlaceDatas = {...resultsPlaceDatas,..._res};
            });
        }
        this.nodeOperatorsReplaceDatas = resultsPlaceDatas;
        /**
         初始状态时 区别是自由流程还是加签
         */
        this.currentFlowingGroup = curFlowingGroup;
        this.currentChoosedItemDataIndex = `${currentStartNodeId}_0`;//${freeStartNodeid}_0
        if (isFree == '1') {
            if (templateid == '-1') {
                this.rightDetailType = 'node';
                this.getFreeNodeSetting(startGroup,`${currentStartNodeId}_0`);
            }else{
                this.rightDetailType = 'isModel_init';
            }
        } else {
            this.rightDetailType = 'signSet';
            if(!isEmpty(curFlowingGroup)){ 
                this.signSetIsReadOnly = true;
                this.rightDetailType = 'node';
                this.getFreeNodeSetting(curFlowingGroup,`${currentStartNodeId}_0`);
            }
        }
        /**
        处理新版数据结构
        */
        /** */
        let _newPoints = {};
        let _curPointMaxX = 50;
        let freeNodeDatasLength = 0;

        const keys = Object.keys(freeNodeDatas);
        keys.map((key)=>{
            let arr = freeNodeDatas[key];
            freeNodeDatasLength += arr.length;
        })

        let freeNodeCurOffsetY = 0 , _everyFreeNodeOffsetY={};
        //计算节点位置数据
        keys.map((key)=>{
            let arr = freeNodeDatas[key];
            _everyFreeNodeOffsetY[key] = freeNodeCurOffsetY;
            arr.map((v,i)=>{
                let curPoints = calculateNodePoint(v,_curPointMaxX,freeNodeDatasLength);
                let ptKey = `${key}_${i}`;
                _newPoints[ptKey] = curPoints;

                let _maxX = this.getMaxXInAllFreeNodePts(curPoints);
                _curPointMaxX = _maxX + this.betweenFreeNodeGap;
            });
            freeNodeCurOffsetY+=2;
        })
        this.everyFreeNodeOffsetY = _everyFreeNodeOffsetY;
        this.wfFreeDatasPoints = _newPoints;
        this.wfFreeDatas = freeNodeDatas;
        this.beforeSavedDatas = freeNodeDatas;
        /****************/
    }
    //获取当前流转到的自由节点
    getcurrentFlowGroup = (groupElement = {}) => {
        let res;
        if(isEmpty(toJS(groupElement))){
            res = null;
        }else{
            const {currentNodeGroup = false,hasNext,next,nodeElement,parallelNodeGroupDatas} = groupElement;
            if(nodeElement){
                if(currentNodeGroup){
                    res = groupElement;
                }
            }else{
                parallelNodeGroupDatas.map(v=>{
                    let _res = this.getcurrentFlowGroup(v);
                    res = _res || res;
                });
            } 
            if(hasNext){
                let _res = this.getcurrentFlowGroup(next);
                res = _res || res;
            }
        }
        return res;
    }
    //初始化所有节点的操作者默认值
    initAllNodesReplaceDatas(data = {}) {
        const {id = '', nodeEntity = {}, hasNext = false, next = {}, parallelNodeGroupDatas = [], nodeElement = true} = data;
        const {operatorReplaceDatas = []} = nodeEntity;
        let res = {};
        if (!nodeElement) {
            parallelNodeGroupDatas.map(v => {
                let _res = this.initAllNodesReplaceDatas(v);
                res = {...res, ..._res};
            });
        } else {
            if (operatorReplaceDatas.length > 0) {
                res[id] = operatorReplaceDatas;
            }
        }
        if (hasNext) {
            let _res = this.initAllNodesReplaceDatas(next);
            res = {...res, ..._res};
        }
        return res;
    }

    //*******处理加签节点数据
    concatFreeFlowNodeDatas(freeDatas = {}, trunkDatas = {}) {
        let cloneDatas = cloneDeep(freeDatas);
        const {startGroup = {}, endGroup = {}} = trunkDatas;
        if (isEmpty(cloneDatas)) {
            startGroup.id = new Date().getTime();
            startGroup.hasNext = true;
            endGroup.id = new Date().getTime() + 1;
            startGroup.next = endGroup;
        } else {
            this.setFreeFlowNodeEndNode(cloneDatas, endGroup);
            startGroup.hasNext = true;
            startGroup.next = cloneDatas;
        }
        return startGroup;
    }

    setFreeFlowNodeEndNode(freeDatas = {}, endGroup = {}) {
        const {hasNext = false, next = {}} = freeDatas;
        if (!hasNext) {
            freeDatas.hasNext = true;
            freeDatas.next = endGroup;
        } else {
            this.setFreeFlowNodeEndNode(next, endGroup);
        }
    }

    //*******
    setCurrentMouseEnterId = (id = '') => {
        this.currentMouseEneterItemId = id;
    }

    loadNodeDetailInfo = () => {
        WORKFLOWDESIGN_API.getFreeNodeSetting(this.currentPostParams).then(result => {
            const {nodeConfigs = [],rejectItems = [],operatorMustInput = false,groupApprovalSettings={}} = result;

            this.operatorMustInput = operatorMustInput;
            this.freeDetailSetConditions = nodeConfigs;
            this.groupApprovalSettings = groupApprovalSettings;
            this.returnBackConditions = [{items: rejectItems}];
            this.returnBackForm = new WeaForm();
            this.returnBackForm.setCondition(this.returnBackConditions);
        });
    }

    getFreeNodeSetting = (nodeInfo = {},posTag='') => {
        const {id = '',nodeEntity={}} = nodeInfo;
        this.currentChoosedItemDataIndex = posTag;
        this.currentChoosedItemId = id;
        // this.curFloatSignNodeId = nodeEntity.id;

        this.detailForm_1 = new WeaForm();
        const condition = cloneDeep(toJS(this.freeDetailSetConditions));
        this.detailForm_1.setCondition(condition);
        this.setFreeNodeSettingInfo(nodeInfo,posTag);
    }

    // 点击节点 设置右侧详细栏信息
    setFreeNodeSettingInfo(nodeInfo,posTag) {
        const {nodeEntity = {}, id = ''} = nodeInfo;
        let {
            allowComments = false, allowModify = '0', allowForward = false, allowTransfer = false, earlyReminder = -1, groupid = 0, loopReminder = false,
            loopRemind = '', remindInterval = '', mustPass = false, nextNodeEditPurview = '2', nodename = '', nodetype = '1', overflowtime = '', overflowtimetype = '0', operators = '',
            reminderInterval = -1, advanceRemind = '', overflowtimehour = '', overflowtimeminute = '', overflowtimedate = '', overflowtimetime = '', signType = '',
            operatorReplaceDatas = [], isrejectremind = '0', ischangrejectnode = '0', isselectrejectnode = '1', isSubmitDirectNode = '0',approvalSettings = ''
        } = nodeEntity;
        nodetype == '3' ? nextNodeEditPurview = '0' : '';//归档节点默认后续节点权限不可以调整
        const operatorObj = this.nodeOperatorsReplaceDatas[id] || operatorReplaceDatas;
        const operatorIds = [];
        operatorObj.map(v => {
            operatorIds.push(v.id);
        });
        let updataObj = {
            nodename,
            operators,
            nodetype: nodetype + '',
            allowModify: (allowModify === true || allowModify == '1') ? '1' : '0',
            allowForward: (allowForward === true || allowForward == '1') ? '1' : '0',
            allowTransfer: (allowTransfer === true || allowTransfer == '1') ? '1' : '0',
            allowComments: (allowComments === true || allowComments == '1') ? '1' : '0',
            nextNodeEditPurview,//RADIO
            syncAllNode: -1,//checkbox
            overflowtimetype: overflowtimetype + '',
            overflowtimehour:overflowtimehour+'',
            overflowtimeminute:overflowtimeminute+'',
            overflowtimedate,
            overflowtimetime,
            advanceRemind: advanceRemind + '',
            earlyReminder,
            loopRemind: loopRemind + '',
            remindInterval: remindInterval + '',
            loopReminder: loopReminder + '',
            loopReminderTime: -1,//SELECT,
            signType: signType + '',
            approvalSettings:approvalSettings
        };
        let returnBackParams = {
            isrejectremind:isrejectremind+'',
            ischangrejectnode:ischangrejectnode+'',
            isselectrejectnode:isselectrejectnode+'',
            isSubmitDirectNode:isSubmitDirectNode+''
        }
        this.tempReturnBackValue = returnBackParams;
        this.rightDetailType = 'node';
        this.currentChoosedBranchId = '';
        this.detailForm_1.updateFields(updataObj, false);
        this.returnBackForm.updateFields(returnBackParams, false);

        let _this = this;
        setTimeout(()=>{
            let updateparams = {operators:{value: operatorIds.join(','), valueObj: toJS(operatorObj)}};
            _this.detailForm_1.updateFields(updateparams, false);
        },0)
    }

    @action
    setWfDesignFreeEditGroup = (branchId = '',posTag='') => {
        this.currentChoosedItemDataIndex = posTag;
        this.currentChoosedBranchId = branchId;
        this.rightDetailType = 'branch';
    }

    setFreeNodeUsers = (elementId = '', ids = '', names = '', datas = [] ,posTag) => {
        this.currentChoosedItemDataIndex = posTag;
        let tempReplace = {};
        tempReplace[elementId] = datas;
        this.nodeOperatorsReplaceDatas = {...this.nodeOperatorsReplaceDatas, ...tempReplace};

        let startId = posTag.split('_')[0];//当前起始点 id
        let dataArrIndex = posTag.split('_')[1];//当前起始点 id 下的数组下标
        let element = this.getFreeObjById(elementId, this.wfFreeDatas[startId][dataArrIndex]);

        let operatorStr = [];
        datas.map((element, index, array) => {
            const multiUserType = this.operatorTransType[element.type];
            operatorStr.push(`${multiUserType}_${element.id}`);
        });
        element.nodeEntity.operators = operatorStr.join(',');
        element.nodeEntity.operatorids = ids;
        this.setFreeNodeSettingInfo(element);
    }
    /**
     *删除方法
     */
    @action
    deleteFreeNodeItem = (deleteId = '',posTag) => {
        this.setCurrentElement_mobile();
        this.deleteItemUtil_v2(deleteId,posTag);
    }

    deleteItemUtil_v2(deleteId = '',posTag) {
        let startId = posTag.split('_')[0];//当前起始点 id
        let dataArrIndex = posTag.split('_')[1];//当前起始点 id 下的数组下标

        let currentWfDatas = mobx.toJS(this.wfFreeDatas[startId][dataArrIndex]);
        let cloneDatas = cloneDeep(currentWfDatas);
        let currentNode = this.getFreeObjById(deleteId, cloneDatas);
        let lastNode = this.getLastObjById(deleteId, cloneDatas);
        let parentNode = this.getFreeObjById(currentNode.parentid, cloneDatas);
        /**当前节点为当前分支第一个节点 且后续节点为一个分支---不允许删除 */
        if (!lastNode && (currentNode.next && !currentNode.next.nodeElement) && parentNode) {
            Modal.confirm({
                title: getLabel('131329', '信息确认'),
                content: getLabel(506876,'此节点后有并行节点，不允许删除！'),
                onOk: () => {
                },
                okText: getLabel(83446, '确定'),
                okCancel: false,
            });
            return;
        } else {
            this.currentMouseEneterItemId = '';
        }
        /** */

        let currentNodeId = currentNode.id + '';
        if (Number(currentNodeId) > 0) {
            this.deleteIds.push(currentNodeId);//判断是否是新加的点
        }
        let _new = {}
        if (lastNode) {
            if (currentNode.hasNext) {
                lastNode.next = currentNode.next;
            } else {
                lastNode.hasNext = false;
                lastNode.next = null;
            }
            _new = this.deleteChangeDatas(lastNode.id, lastNode, cloneDatas);
        } else {
            if (parentNode) {
                let parentId = parentNode.id;
                let parallArr = parentNode.parallelNodeGroupDatas;
                // let newArr = parallArr.filter(v => v.id != deleteId);
                let newArr = [];
                parallArr.map((v,i)=>{
                    if(v.id == deleteId){
                        v = null;
                    }
                    newArr.push(v);
                });
                let currentNextNode;
                if (currentNode.hasNext) {
                    currentNextNode = currentNode.next;
                    newArr.map((v,i)=>{
                        if(!v){
                            newArr[i] = currentNextNode;
                        }
                    })
                    // newArr.push(currentNextNode);
                }
                newArr = newArr.filter(v=>v);
                if (newArr.length >= 2) {
                    parentNode.parallelNodeGroupDatas = newArr;
                } else {
                    if (!newArr[0]) {
                        return;
                    }
                    if (Number(parentNode.id) > 0) {
                        this.deleteIds.push(parentNode.id);//判断是否是新加的点
                    }
                    let uniqueItem = this.getFreeObjById(newArr[0].id,currentWfDatas);
                    uniqueItem.freeStartNodeid = parentNode.freeStartNodeid;
                    uniqueItem.freeEndNodeid = parentNode.freeEndNodeid;
                    if (parentNode.hasNext) {
                        let parent_NextNode = cloneDeep(parentNode.next);
                        parent_NextNode = this.getFreeObjById(parent_NextNode.id,currentWfDatas);

                        if (uniqueItem.hasNext) {//找到最后一个元素 将父级next赋值给他的next,并且所有next的parentid 都需改变
                            let finalNext = this.findAllNextAndReturnFinal(uniqueItem, parentNode.parentid);
                            finalNext.hasNext = true;
                            finalNext.next = parent_NextNode;
                        } else {
                            uniqueItem.hasNext = true;
                            uniqueItem.parentid = parentNode.parentid;
                            uniqueItem.next = parent_NextNode;
                        }
                        parentNode = uniqueItem;
                    } else {
                        //直接将parent换为当前元素
                        let finalNext = this.findAllNextAndReturnFinal(uniqueItem, parentNode.parentid);
                        uniqueItem.parentid = parentNode.parentid;
                        parentNode = {...uniqueItem};
                    }
                    // 变串行
                }
                _new = this.deleteChangeDatas(parentId, parentNode, cloneDatas);
                //从数组中删除当前
                // 如只剩下一个元素，变为串行
            } else {
                if (currentNode.hasNext) {
                    _new = currentNode.next;
                    _new.freeStartNodeid = currentNode.freeStartNodeid;
                    _new.freeEndNodeid = currentNode.freeEndNodeid;
                }
            }
        }
        this.svgPathLine = {};
        /***************/
        if(isEmpty(_new)){
            delete this.wfFreeDatas[startId];
        }else{
            this.wfFreeDatas[startId][dataArrIndex] = _new;
        }
        

        let _newPoints = {};
        let _curPointMaxX = 50;
        let freeNodeDatasLength = 0;
        for(let key in this.wfFreeDatas){
            let arr = this.wfFreeDatas[key];
            freeNodeDatasLength += arr.length;
        }
        let freeNodeCurOffsetY = 0 , _everyFreeNodeOffsetY={};
        for(let key in this.wfFreeDatas){
            let arr = this.wfFreeDatas[key];
            _everyFreeNodeOffsetY[key] = freeNodeCurOffsetY;
            arr.map((v,i)=>{
                let curPoints = calculateNodePoint(v,_curPointMaxX,freeNodeDatasLength);
                let ptKey = `${key}_${i}`;
                _newPoints[ptKey] = curPoints;
                let _maxX = this.getMaxXInAllFreeNodePts(curPoints);
                _curPointMaxX = _maxX + this.betweenFreeNodeGap;
            });
            freeNodeCurOffsetY+=2;
        }
        this.everyFreeNodeOffsetY = _everyFreeNodeOffsetY;
        this.wfFreeDatasPoints = _newPoints;
        /************************/

        /**
        1.右侧选择的是节点属性 并且删除的是此节点
        2.选择的是分支，并且分支最后只剩下一个节点 及 当前分支不存在
        切换右侧信息栏状态 选中创建节点
         */
        let curSelectedElementId = '';
        if(this.rightDetailType == 'node'){
            curSelectedElementId = this.currentChoosedItemId;
        }else if(this.rightDetailType == 'branch'){
            curSelectedElementId = this.currentChoosedBranchId;
        }
        let selectedElement = this.getFreeObjById(curSelectedElementId,_new);
        if(!selectedElement){ // 之前选中的element不存在了，选中创建节点
            if(this.currentPostParams.templateid != -1){
                this.rightDetailType = 'isModel_init';
            }else{
                if (this.currentPostParams.isFree == '1'){//自由流程
                    this.getFreeNodeSetting(this.freeWfTrunkNodes.startGroup || {},posTag);
                }else{//加签
                    if(!isEmpty(this.currentFlowingGroup) && !isEmpty(_new)){
                        this.getFreeNodeSetting(this.currentFlowingGroup || {},posTag);
                    }else{
                        this.rightDetailType = 'signSet';
                    }
                }
            }
            
        }
        /***********************/
    }

    deleteChangeDatas(changeId = '', willBeData = {}, datasArr = {}) {
        let cloneDatas = cloneDeep(datasArr);
        if (cloneDatas.id == changeId) {
            cloneDatas = {...willBeData};
        } else {
            if (cloneDatas.hasNext) {
                cloneDatas.next = {...this.deleteChangeDatas(changeId, willBeData, cloneDatas.next)};
            }
            if (!cloneDatas.nodeElement) {
                let cloneArr = cloneDatas.parallelNodeGroupDatas;
                cloneArr.map((v, i) => {
                    cloneArr[i] = {...this.deleteChangeDatas(changeId, willBeData, v)};
                });
                cloneDatas.parallelNodeGroupDatas = cloneArr;
            }
        }
        return cloneDatas;
    }

    findAllNextAndReturnFinal(data = {}, parentid = '') {//找到元素所有下级改变parentid 并返回最后一个
        let finalNext = null;
        if (data.hasNext) {
            let next = data.next;
            next.parentid = parentid;
            finalNext = this.findAllNextAndReturnFinal(next, parentid);
        } else {
            finalNext = data;
        }
        return finalNext;
    }

    // ******************************
    initNewAddElement(options = {}) {//生成一个当前添加的element对象 并且维护节点默认属性
        const {nodeid = 0} = this.currentPostParams;
        let approvalSettings = this.groupApprovalSettings[`${nodeid}`]||'';
        let element = {
            id: this.currentAddDataId * -1,
            nodeChartEntity:{
                del:true,
                edit:true,
                addParall:true,
                addNext:true
            },
            nodeElement: true,
            groupStatus:'0',
            hasNext: false,
            next: null,
            parallelNodeGroupDatas: [],
            parentid: '',
            nodeEntity: {
                nodename: getLabel(516487,'节点名称') + this.currentAddDataId,
                operatortype: 'resource',
                operators: '',
                nodetype: '1',
                mustPass: false,
                signType: '1',//会签属性  默认会签
                nextNodeEditPurview: '1',//后续节点编辑权限  默认仅允许添加新节点
                allowForward: '1',//允许转发
                allowTransfer: '1',//允许转办
                allowComments: '1',//允许意见征询
                overflowtimetype: '0',//超时时间
                advanceRemind: '0',//提前提醒,

                isrejectremind: '0', //流程退回提醒
                ischangrejectnode: '0', // 退回时可设置提醒节点,
                isselectrejectnode: '1',//退回方式
                isSubmitDirectNode: '0',//退回后再提交到达节点

                overflowtimehour:0,
                overflowtimeminute:0,
                overtimeToNextOperator : '0',//超时自动流转至下一操作者
                afterLoopRemind : '0',//节点超时 后 开启循环 提醒
                afterRemindInterval : '5',//节点超时 后  间隔时间
                beforeLoopRemind : '0',//节点超时 前 开启循环 提醒
                beforeRemindInterval : '5',//节点超时 前  间隔时间
                approvalSettings:approvalSettings,//新建节点默认当前节点签批值
            }
        }
        return {...element, ...options}
    }

    beSerialNodes = (choosedId = '',dataIndex='') => {//串行
        let _cloneArr = cloneDeep(mobx.toJS(this.wfFreeDatas));
        /**判断当前  dataIndex 是否存在 存在则直接获取对应数据 不存在则新增*/
        let currentElment = {};
        let startId = dataIndex.split('_')[0];//当前起始点 id
        let dataArrIndex = dataIndex.split('_')[1];//当前起始点 id 下的数组下标
        if(_cloneArr[startId]){
            !dataArrIndex ? dataArrIndex = 0 : ''; //root 的时候 暂时index为 0 
            if(_cloneArr[startId][dataArrIndex]){
                currentElment = _cloneArr[startId][dataArrIndex];
            }
        }else{
            dataArrIndex = 0;
        }
        /****************/
        let serialObj = this.getFreeObjById(choosedId, currentElment) || {};
        let lastNext;
        let options = {
            parentid: serialObj.parentid,
        }
        if (choosedId == 'root') {
            let newElement = this.initNewAddElement(options);
            
            // newElement.freeEndNodeid = dataIndex;
            let _existedDatas = cloneDeep(currentElment);
            if(!isEmpty(_existedDatas)){
                newElement.hasNext = true;
                newElement.next = _existedDatas;
                newElement.freeStartNodeid = _existedDatas.freeStartNodeid;
                newElement.freeEndNodeid = _existedDatas.freeEndNodeid;
            }else{
                newElement.freeStartNodeid = dataIndex;
                let {flowType='1'} = this.currentSignSetNode;
                if(this.currentPostParams.isFree == '1') flowType = '2';
                let tempFreeEndNodeIds = dataIndex;
                if(flowType == '2') {
                    let endNodeIds = [];
                    this.allValidNodesNodeLinks[dataIndex].map(v=>{
                        endNodeIds.push(v.descnode);
                    });
                    tempFreeEndNodeIds = endNodeIds.join(',');
                }
                newElement.freeEndNodeid = tempFreeEndNodeIds;
            }
            currentElment = newElement;
        }else{
            if (serialObj.hasNext) {
                lastNext = serialObj.next;
                options.hasNext = true;
                options.next = lastNext;
                serialObj.next = this.initNewAddElement(options);
            } else {
                serialObj.hasNext = true;
                serialObj.next = this.initNewAddElement(options);
            }
        }
        this.currentAddDataId++;
        this.wfFreeDatas[startId] = [currentElment]
        /** 计算当前点位置 */
        let _newPoints = {};
        let _curPointMaxX = 50;
        let freeNodeDatasLength = 0;
        const tempFreeDatas = mobx.toJS(this.wfFreeDatas);
        for(let key in tempFreeDatas){
            let arr = tempFreeDatas[key];
            freeNodeDatasLength += arr.length;
        }
        let freeNodeCurOffsetY = 0 , _everyFreeNodeOffsetY={};
        for(let key in tempFreeDatas){
            let arr = tempFreeDatas[key];
            _everyFreeNodeOffsetY[key] = freeNodeCurOffsetY;
            arr.map((v,i)=>{
                let curPoints = calculateNodePoint(v,_curPointMaxX,freeNodeDatasLength);
                let ptKey = `${key}_${i}`;
                _newPoints[ptKey] = curPoints;

                let _maxX = this.getMaxXInAllFreeNodePts(curPoints);
                _curPointMaxX = _maxX + this.betweenFreeNodeGap;
            });
            freeNodeCurOffsetY+=2;
        }
        this.everyFreeNodeOffsetY = _everyFreeNodeOffsetY;
        this.wfFreeDatasPoints = _newPoints;
    }
    beParallelWithCurNode = (choosedId = '',dataIndex='') => {//与本节点并行

        let _allDatasArr = cloneDeep(mobx.toJS(this.wfFreeDatas));
        let startId = dataIndex.split('_')[0];
        let dataArrIndex = dataIndex.split('_')[1] * 1;
        let _cloneArr = _allDatasArr[startId][dataArrIndex];

        let choosedElement = this.getFreeObjById(choosedId, _cloneArr) || {};
        let preObj = this.getLastObjById(choosedElement.id, _cloneArr);
        let parentElement = this.getFreeObjById(choosedElement.parentid, _cloneArr) || {};
        let currentChoosedObj = cloneDeep(mobx.toJS(choosedElement));
        let paralleId = (this.currentAddDataId * -1) + 'branch';

        currentChoosedObj.hasNext = false;
        currentChoosedObj.next = null;
        currentChoosedObj.parentid = paralleId;
        let paralleObj = {parallelNodeGroupDatas: []};
        if (preObj != null || (!choosedElement.parentid || isEmpty(parentElement))) {
            paralleObj = {//初始并行分支数据
                id: paralleId,
                nodeChartEntity:{
                    del:true,
                    edit:true,
                    addParall:true,
                    addNext:true
                },
                groupStatus:'0',
                hasNext: choosedElement.hasNext,
                next: choosedElement.next,
                mergeType: '1',
                mergeValue: '100',
                requestid: '',
                nodeElement: false,
                parentid: choosedElement.parentid,
                parallelNodeGroupDatas: [currentChoosedObj]
            }
        }

        let newElement = this.initNewAddElement({parentid: paralleId});
        paralleObj.parallelNodeGroupDatas.push(newElement);
        if (preObj != null) {
            preObj.next = paralleObj;
        } else {
            paralleObj.freeStartNodeid = choosedElement.freeStartNodeid;
            paralleObj.freeEndNodeid = choosedElement.freeEndNodeid;
            if (choosedElement.parentid && !isEmpty(parentElement)) {
                let parentArr = parentElement.parallelNodeGroupDatas;
                newElement.parentid = choosedElement.parentid;
                parentArr.map((element, index) => {
                    if (choosedElement.id == element.id) {
                        parentElement.parallelNodeGroupDatas.splice(index + 1, 0, newElement);
                    }
                })
            } else {
                _cloneArr = paralleObj;
            }
        }
        this.currentAddDataId++;
        this.wfFreeDatas[startId][dataArrIndex] = _cloneArr;

        /******/
        let _newPoints = {};
        let _curPointMaxX = 50;
        let freeNodeDatasLength = 0;
        for(let key in this.wfFreeDatas){
            let arr = this.wfFreeDatas[key];
            freeNodeDatasLength += arr.length;
        }
        let freeNodeCurOffsetY = 0 , _everyFreeNodeOffsetY={};
        for(let key in this.wfFreeDatas){
            let arr = this.wfFreeDatas[key];
            _everyFreeNodeOffsetY[key] = freeNodeCurOffsetY;
            arr.map((v,i)=>{
                let curPoints = calculateNodePoint(v,_curPointMaxX,freeNodeDatasLength);
                let ptKey = `${key}_${i}`;
                _newPoints[ptKey] = curPoints;
                let _maxX = this.getMaxXInAllFreeNodePts(curPoints);
                _curPointMaxX = _maxX + this.betweenFreeNodeGap;
            });
            freeNodeCurOffsetY+=2;
        }
        this.everyFreeNodeOffsetY = _everyFreeNodeOffsetY;
        this.wfFreeDatasPoints = _newPoints;
        // this.wfFreeDatas = _cloneArr;
    }
    getMaxXInAllFreeNodePts = (points={}) => {
        let maxX = 0;
        for(let key in points){
            let objPts = points[key];
            maxX = maxX < objPts.x ? objPts.x : maxX;
        }
        return maxX;
    }
    //审批节点退回设置
    openReturnBackSetting = (bool = false,initDatas=false) => {
        /** 获取当前 准确位置上的自由节点数据*/
        let startId =  this.currentChoosedItemDataIndex.split('_')[0];
        let datasIndex = '' , currentFreeDatas = {};
        if(startId != ''){
            datasIndex =  this.currentChoosedItemDataIndex.split('_')[1];
            currentFreeDatas = this.wfFreeDatas[startId][datasIndex];
        }
        /************/
        this.returnBackDialogShow = bool;
        if(initDatas){
            let currentElement = this.getFreeObjById(this.currentChoosedItemId,currentFreeDatas) || {};
            let {isrejectremind='0',ischangrejectnode='0',isselectrejectnode='1',isSubmitDirectNode='0'} = currentElement.nodeEntity; 
            this.returnBackForm.updateFields({
                isrejectremind:isrejectremind+'',
                ischangrejectnode:ischangrejectnode+'',
                isselectrejectnode:isselectrejectnode+'',
                isSubmitDirectNode:isSubmitDirectNode+''
            },false);
            this.tempReturnBackValue = {isrejectremind:isrejectremind+'',ischangrejectnode:ischangrejectnode+'',
            isselectrejectnode:isselectrejectnode+'',isSubmitDirectNode:isSubmitDirectNode+''};
        }
    }

    // utils - function
    getLastObjById(id = '', mapData = cloneDeep(mobx.toJS(this.wfFreeDatas))) {
        let lastObj = null;
        mapData = mapData || {};
        if (mapData.hasNext) {
            if (mapData.next.id == id) {
                lastObj = mapData;
            } else {
                let res = this.getLastObjById(id, mapData.next);
                lastObj = res ? res : lastObj;
            }
        }
        if (!mapData.nodeElement) {
            let parallelArr = mapData.parallelNodeGroupDatas || [];
            parallelArr.map(v => {
                let res = this.getLastObjById(id, v);
                lastObj = res ? res : lastObj;
            })
        }
        return lastObj;
    }

    getCurrentGroup = (nodeGroup = {}) =>{
        const {nodeElement, hasNext = false,isCurrentNodeGroup = false,parallelNodeGroupDatas = [],next = {}} = nodeGroup;
        let currentGroup = null;
        if(nodeElement) {
            if(isCurrentNodeGroup) {
                currentGroup = nodeGroup;
            }
        } else {
            parallelNodeGroupDatas.map((item) =>{
                let tempGroup = getCurrentGroup(item);
                if(tempGroup != null) {
                    currentGroup = tempGroup;
                }
            })
        }
        if(hasNext) {
            let tempGroup = getCurrentGroup(next);
            if(tempGroup != null) {
                currentGroup = tempGroup;
            }
        }
        return currentGroup;
    }

    getFreeObjById = (id = '', mapData = cloneDeep(mobx.toJS(this.wfFreeDatas))) => {
        let freeObj = null;
        mapData = mapData || {};
        if (mapData.id && mapData.id == id) {
            freeObj = mapData;
        }
        if (mapData.hasNext) {
            let res = this.getFreeObjById(id, mapData.next);
            freeObj = res ? res : freeObj;
        }
        if (mapData.parallelNodeGroupDatas && mapData.parallelNodeGroupDatas.length > 0) {
            mapData.parallelNodeGroupDatas.map(v => {
                let res = this.getFreeObjById(id, v);
                freeObj = res ? res : freeObj;
            })
        }
        return freeObj;
    }
    //
    setOrginWfNodesInfo = (data = {}) => {
        const {createNodeInfo , cellMaxHeight} = data;
        const {currentNode = {}, curNextNode, allNodesInfo = []} = createNodeInfo;//curNextNode is array
        /**初始化固定流程数据 */
        let validDatas = {
            cellMaxHeight,
            allValidNodes:allNodesInfo,
            currentStartNode : currentNode,
            currentEndNodes : curNextNode
        }
        this.validWorkFlowDatas = validDatas;
        this.calculateValidNodePosition(validDatas);
        /*******************/
        let obj = {
            nextOrginNode: (curNextNode && curNextNode[0]) ? curNextNode[0].nodeId : '',
            allOrginNodes: allNodesInfo,
            curNextNode:curNextNode[0]
        }
        if (this.circulationOrginNode.startOrginNodeId == '') {
            obj['startOrginNodeId'] = this.circulationOrginNode['startOrginNodeId'] || currentNode.nodeId;
        }
        this.circulationOrginNode = {...this.circulationOrginNode, ...obj};
    }
    /** 计算固定节点位置 */
    calculateValidNodePosition = (validDatas={}) => {
        const { allValidNodes = [] , cellMaxHeight} = validDatas;
        let resPosition = {};
        allValidNodes.map(v=>{
            const geo = v.geometry;
            const geoPos = {
                x : geo.x , 
                y : geo.y , 
                width : geo.width , 
                height : geo.height
            };
            resPosition[v.nodeId] = {
                x : geoPos.x + geoPos.width / 2,
                y : cellMaxHeight - (geoPos.y + geoPos.height), //固定节点距离下部自由绘制区域的差值
            }
        });
        this.allValidNodesPostions = resPosition;
    }
    // 改变流程加签流转结束后的节点位置 回到本节点 || 自动转入下一节点
    signSetChangeBackNode = (v) => {
        const { currentStartNode , currentEndNodes} = this.validWorkFlowDatas;
        const curDatasIndexId = this.currentValidStartNodeId;
        if(this.wfFreeDatas[curDatasIndexId] && this.wfFreeDatas[curDatasIndexId][0]){
            if (v == '1') {
                this.wfFreeDatas[curDatasIndexId][0].freeEndNodeid = this.wfFreeDatas[curDatasIndexId][0].freeStartNodeid;
            }else{
                let ids = [];
                this.allValidNodesNodeLinks[curDatasIndexId].map(v=>{
                    ids.push(v.descnode);
                });
                this.wfFreeDatas[curDatasIndexId][0].freeEndNodeid = ids.join(',');
            }
        }
        // v = 1 - 当前节点 || v = 2 - 下一节点
        this.currentSignSetNode = {...this.currentSignSetNode, flowType: v};
        if (v == '1') {
            this.circulationOrginNode.endOrginNodeId = this.circulationOrginNode.startOrginNodeId;
        } else {
            this.circulationOrginNode.endOrginNodeId = this.circulationOrginNode.curNextNode.nodeId;
        }
    }
    //清除当前选中的节点 和 分支状态
    clearCurrentChooseState = () => {
        this.currentMouseEneterItemId = '';
    }

    judgeFreeNodeData = () => {
        const cloneDatas = cloneDeep(mobx.toJS(this.wfFreeDatas));
        let judgeResult = true;
        for(let key in cloneDatas){
            let arr = cloneDatas[key];
            for(let index = 0; index < arr.length; index++ ){
                let posTag = `${key}_${index}`;
                judgeResult = this.checkFreeDataPassed(arr[index],posTag);
                if(!judgeResult) {
                    break;
                }
            }
            if(!judgeResult) {
                break;
            }
        }
        return judgeResult;
    }

    //保存流程图数据
    saveFreeNodeData = (callback,params={}) => {
        this.loading = true;
        let  judgeResult = this.judgeFreeNodeData();
        if(judgeResult) {
            const cloneDatas = cloneDeep(mobx.toJS(this.wfFreeDatas));
            let curDatasIndexId = this.currentValidStartNodeId;
            if(this.currentPostParams.templateid != '-1'){
                let key = Object.keys(cloneDatas)[0];
                curDatasIndexId = key;
            }
            let postChatDatas = cloneDatas[curDatasIndexId] ? JSON.stringify(cloneDatas[curDatasIndexId][0]) : '{}';
            const submitParams = {
                ...this.currentPostParams,
                maxGroupNum : this.currentAddDataId,
                chartDatas: postChatDatas,
                deleteIds: this.deleteIds.join(','),
                ...params,
            };
            message.destroy();
            message.loading(getLabel(23278, '正在保存，请稍候...'), 0);
            WORKFLOWDESIGN_API.saveFreeNodeInfo(submitParams).then((result = {}) => {
                message.destroy();
                this.loading = false;
                const {success} = result;
                if(success) {
                    message.success(getLabel(83551, '保存成功！'));
                }
                callback && callback(result);//关闭编辑弹框
                if(submitParams.method != 'template'){
                    this.doActionToDatas_2(result,submitParams);
                }
            });
        } else {
            this.loading = false;
        }
        this.saveCheckResult = {};
    }

    //验证自由流程数据是否通过 验证必填项
    checkFreeDataPassed(data = {},posTag) {
        const {nodeElement = false, hasNext = false, next = {}, parallelNodeGroupDatas = [], nodeEntity = {}, id = ''} = data;
        const formParams = this.detailForm_1.getFormParams();
        if (nodeElement) {
            const {
                operators = '', overflowtimetype = '', overflowtimedate = '', overflowtimetime = '', overflowtimehour = '', overflowtimeminute = '',
                nodename = '', nodetype = '',advanceRemind=''
            } = nodeEntity;
            if (!(nodetype == '0' || nodetype == '3')) {//创建和归档节点不验证
                let curEltTip = this.saveCheckResult[id] || {name: nodename, tip: [],warning:[]};//当前已经存储好的提示信息
                if (nodename.trim() == '') {
                    curEltTip['tip'].push(getLabel(15070,'节点名称'));
                    this.saveCheckResult[id] = curEltTip;
                    this.showDetailFormError(data,{key:'nodename'},posTag);
                    return false;
                }
                if(this.operatorMustInput && operators.trim() == '') {
                    curEltTip['tip'].push(getLabel(99,'操作者'));
                    this.saveCheckResult[id] = curEltTip;
                    this.showDetailFormError(data,{key:'operators'},posTag);
                    return false;
                }
                if (overflowtimetype == '2') {
                    if (overflowtimedate == '') {//超时时间-日期
                        curEltTip['tip'].push(getLabel(22823,'日期'));
                        this.saveCheckResult[id] = curEltTip;
                        this.showDetailFormError(data,{key:'overflowtimedate'},posTag);
                        return false;
                    }
                } else if (overflowtimetype == '1' ) {
                    if (overflowtimehour === '') {//超时时间-小时
                        curEltTip['tip'].push(getLabel(506877,'超时时间-小时'));
                        this.saveCheckResult[id] = curEltTip;
                        this.showDetailFormError(data,{key:'overflowtimehour'},posTag);
                        return false;
                    }
                    if (overflowtimeminute === '') {//超时时间-分钟
                        curEltTip['tip'].push(getLabel(15049,'分钟'));
                        this.saveCheckResult[id] = curEltTip;
                        this.showDetailFormError(data,{key:'overflowtimeminute'},posTag);
                        return false;
                    }
                    if (overflowtimeminute == '0' && overflowtimehour == '0') {//超时时间-分钟 小时都是0
                        curEltTip['tip'].push(getLabel(15049,'分钟'));
                        this.saveCheckResult[id] = curEltTip;
                        this.showDetailFormError(data,{key:'hour_minute',name:nodename},posTag);
                        return false;
                    }
                    if(advanceRemind*1 > (overflowtimehour*60 + overflowtimeminute*1)){
                        curEltTip['warning'].push(getLabel(506878,'超时时间小于提前提醒时间！'));
                        this.saveCheckResult[id] = curEltTip;
                        this.showDetailFormError(data,{key:'advanceRemind',name:nodename},posTag);
                        return false;
                    }
                }else if(advanceRemind*1 > overflowtimetype){
                    curEltTip['warning'].push(getLabel(506878,'超时时间小于提前提醒时间！'));
                    this.saveCheckResult[id] = curEltTip;
                    this.showDetailFormError(data,{key:'advanceRemind',name:nodename},posTag);
                    return false;
                }
            }
        } else {
            let arr = cloneDeep(parallelNodeGroupDatas);
            let judgeResult = true;
            for (let index  = 0;index < arr.length; index ++) {
                judgeResult = this.checkFreeDataPassed(arr[index],posTag);
                if(!judgeResult) {
                    break;
                }
            }
            if(!judgeResult) return false;
        }
        if (hasNext) {
           return this.checkFreeDataPassed(next,posTag);
        } else {
            return true;
        }
    }
    showDetailFormError = (element={},options={},posTag) => {
        this.getFreeNodeSetting(element,posTag);
        if(options.key && options.key != 'nodename' && options.key != 'operators'){
            this.rightDetailShowSearchGroup = {//记录右侧操作面板的显隐
                "0":true,
                "1":true,
                "2":true,
            };
        }
        const formParams = this.detailForm_1.getFormParams();
        if(!isEmpty(options)){
            const { key = 'advanceRemind' , tip = '' ,name = ''} = options;
            if(options.key == 'advanceRemind'){
                let msgContent  = `【${name}】：${getLabel(506879,'超时时间未设置或设置的超时时间小于提前提醒时间！')}`;
                message.destroy();
                message.warning(msgContent,5);
            }else if(key == 'hour_minute'){
                let msgContent  = `【${name}】：${getLabel(506880,'超时时间必须大于等于一分钟！')}`;
                message.destroy();
                message.warning(msgContent);
            }
        }
        this.detailForm_1.validateForm().then(f=>{
            if(f.isValid){}
            else{f.showErrors();}
        });
    }
    // 清除状态
    clearMobxState = () => {
        this.wfFreeDatas = {};
        this.wfFreeDatasPoints = {};
    }
    /** 存为模板 */
    @action
    saveAsTemplate = (bool) => {
        let judgeResult = this.judgeFreeNodeData();
        if(judgeResult) {
            this.saveAsTempModalShow = bool;
            bool ? this.saveAsTempForm = new WeaForm() : '';
            if(bool){
                WORKFLOWDESIGN_API.getAddTemplateBaseData().then((result) => {
                    const {templateBaseInfo = []} = result;
                    let condition = [{
                        items: templateBaseInfo
                    }];
                    this.saveAsTempCondition = condition;
                    this.saveAsTempForm.setCondition(condition);
                    this.saveAsTempForm.initFormFields(condition);
                });
            }
        }
    }
    saveAsTempSave = (reLoadTemplateList) => {
        const formParams = this.saveAsTempForm.getFormParams();
        let postParams = {
            ...formParams,
            method:'template'
        }
        this.saveFreeNodeData((result)=>{
            const { success = false , id = '',isRepeat = false} = result;
            if(!success) {
                message.destroy();
                if(isRepeat) {
                    message.warning(getLabel(386286,'"名称"已存在，请重新输入！'));
                } else {
                    message.error(getLabel(84544,'保存失败！'));
                }
            } else {
                this.saveAsTempModalShow = false;
                //刷新列表
                if(typeof reLoadTemplateList == 'function') {
                    reLoadTemplateList();
                }
            }
        },postParams);
    }
    /**从模板导入 */
    @action
    setModelImportDialogShow = (bool) => {
        this.modelImportModelShow = bool;
        if (bool) {
            if (isEmpty(toJS(this.modelAdCondition))) {
                WORKFLOWDESIGN_API.getAddTemplateBaseData().then((result) => {
                    const {advanceCondition = {}, addTemplateTabs = [], templateBaseInfo = [], addShareForm = {}} = result;
                    // const addCondition = [{
                    //     items: advanceCondition
                    // }];
                    const addCondition = [advanceCondition];
                    this.modelAdCondition = addCondition;
                    this.importModelForm.setCondition(addCondition);
                    this.importModelForm.initFormFields(addCondition);
                });
            } else {
                this.importModelForm.resetConditionValue();
            }
            this.searchExistedModelList();
        }
    }
    @action
    setImportModalAdShow = (bool) => {
        this.importModalAdShow = bool;
    }
    @action
    searchExistedModelList = () => {
        let postParams = {
            isModelImport: 1
        };
        const formParams = this.importModelForm.getFormParams();
        postParams = {...postParams,...formParams};
        WORKFLOWDESIGN_API.getFlowTemplateList(postParams).then((result) => {
            const {sessionkey = ''} = result;
            this.importModelTableStore.getDatas(sessionkey, 1, "");
        });
    }
    @action
    postImportModelDatas = (params = {}) => {
        this.loading = true;
        this.setModelImportDialogShow(false);
        const {templateid = -1,requestid = -1} = this.currentPostParams;
        //手动切换过当前节点的流转结后设置项，则取设置，否则取默认值 流转至下一节点
        let endId = this.circulationOrginNode.endOrginNodeId == '' ? this.circulationOrginNode.nextOrginNode : this.circulationOrginNode.endOrginNodeId;
        let postParams = {
            requestid,
            templateid,
            freeStartNodeid: this.circulationOrginNode.startOrginNodeId,
            freeEndNodeid: endId
        };
        postParams = {...postParams, ...params};
        WORKFLOWDESIGN_API.importFromTemplate(postParams).then((result) => {
            this.doActionToDatas_2(result, postParams,true);
            this.loading = false;
        });
    }
    /******************/
    @action
    setPopOperatorsPanemParams = (params = {}) => {
        this.popOperatorsPanelParams = {...this.popOperatorsPanelParams,...params};
    }

    /**移动端特殊处理 */
    @action
    setCurrentElement_mobile = (element={},isBranch=false,posTag='') => {
        if(!isBranch){
           this.currentChoosedBranchId = ''; 
        }
        this.mobileChoosedElementIndex = posTag;
        this.mobileCurrentEditGroupId = element.id;
        this.mobileChoosedElement = element;
    }
    //根据移动端返回的节点数据替换当前原始数据
    @action
    setReturnGroupValue_mobile = (data={},posTag='') => {
        let startId = posTag.split('_')[0];//当前起始点 id
        let dataArrIndex = posTag.split('_')[1];//当前起始点 id 下的数组下标
        let _tempDatas = {};
        if(startId){
            _tempDatas = this.wfFreeDatas[startId][dataArrIndex] || {};
        }

        const id = this.mobileCurrentEditGroupId;
        const cloneDatas = cloneDeep(toJS(_tempDatas));
        let _replaceDatas = {};
        _replaceDatas[data.id || ''] = data.nodeEntity?data.nodeEntity.operatorReplaceDatas:[];
        let res = this.setDatasByGroupId_mobile(id,cloneDatas,data);
        // this.wfFreeDatas = res;
        this.wfFreeDatas[startId][dataArrIndex] = res;
        this.nodeOperatorsReplaceDatas = {...this.nodeOperatorsReplaceDatas,..._replaceDatas};
        this.mobileChoosedElement = data;
        // localStorage.aaaa = JSON.stringify(cloneDatas);
    }
    @action
    setDatasByGroupId_mobile = (_id , cloneDatas = {} , data={}) => {
        const {id='' , hasNext , next , nodeElement , parallelNodeGroupDatas=[]} = cloneDatas;
        if(id == _id){
            cloneDatas = data;
        }else{
            if(!nodeElement){
                parallelNodeGroupDatas.map((v,i)=>{
                    let res = this.setDatasByGroupId_mobile(_id,v,data);
                    parallelNodeGroupDatas[i] = v;
                });
            }
            if(hasNext){
                let res = this.setDatasByGroupId_mobile(_id,next,data);
                cloneDatas.next = res;
            }
        }
        return cloneDatas;
    }

    @action('渲染组件')
    renderComponent = () =>{
        this.componentNeedRender = new Date().getTime();
    }

    updateDetailFormParams = (detailFormParams = {}) => {
        this.detailForm_1.updateFields(detailFormParams);
    }
}